#pragma once

#include "Vector3.h"
#include "Ray.h"
#include "Hitable.h"
#include "Material.h"


class  Sphere:public Hitable
{
public:
	Vector3 center;
	float radius;
	Material* pMaterial;

	Sphere() {}
	Sphere(Vector3 center, float radius) :
		center(center),
		radius(radius)
	{}
	Sphere(Vector3 center, float radius, Material* mat) :
		center(center),
		radius(radius),
		pMaterial(mat)
	{}

	virtual bool hit(const Ray& r, float t_min, float t_max, HitRecord& rec)  const override;

	float hit_sphere(const Vector3 center, float radius, const Ray& r) {
		Vector3 oc = r.origin() - center;
		float a = dot(r.B, r.B);
		float b = 2 * dot(r.B, oc);
		float c = dot(oc, oc) - radius * radius;
		float discriminant = b * b - 4 * a*c;
		return discriminant >= 0;
	}
	float hit_sphere_Normal(const Vector3 center, float radius, const Ray& r) {
		Vector3 oc = r.origin() - center;
		float a = dot(r.B, r.B);
		float b = 2 * dot(r.B, oc);
		float c = dot(oc, oc) - radius * radius;
		float discriminant = b * b - 4 * a*c;
		if (discriminant < 0)
		{
			return -1;
		}
		else
		{
			return (-b - sqrt(discriminant)) /(2.0*a);
		}
	}

	Vector3 Color(const Ray& r) {
		if (hit_sphere(Vector3(0, 0, -1), 0.5, r)) {
			return Vector3(1, 0, 0);
		}
		Vector3 unit_direction = unit_vector(r.direction());
		float t = abs(unit_direction.y());
		return (1.0 - t)*Vector3(1.0, 1.0, 1.0) + t * Vector3(0, 0, 1.0);
	}

	Vector3 Color_Normal(const Ray& r) {
		float  t = hit_sphere_Normal(Vector3(0, 0, -1), 0.5, r);
		if (t >= 0) {
			Vector3 N = unit_vector(r.A + t * r.B - Vector3(0, 0, -1));
			return 0.5*(Vector3(1, 1, 1) + N);
		}
		Vector3 unit_direction = unit_vector(r.direction());
		t = abs(unit_direction.y());
		return Vector3(1.0, 1.0, 1.0) ;
	}
private:

};


bool Sphere::hit(const Ray& r, float t_min, float t_max, HitRecord& rec)  const {
	Vector3 oc = r.origin() - center;
	float a = dot(r.B, r.B);
	float b = 2 * dot(r.B, oc);
	float c = dot(oc, oc) - radius * radius;
	float discriminant = b * b - 4 * a*c;
	if (discriminant < 0)
	{
		return false;
	}
	float temp = (-b - sqrt(discriminant)) / (2.0*a);
	if (temp < t_max && temp > t_min)
	{
		rec.t = temp;
		rec.p = r.point_at_parameter(rec.t);
		rec.normal = (rec.p - center) / radius;
		rec.pMaterial = pMaterial;
		return true;
	}
	temp = (-b + sqrt(discriminant)) / (2.0*a);
	if (temp < t_max && temp > t_min)
	{
		rec.t = temp;
		rec.p = r.point_at_parameter(rec.t);
		rec.normal = (rec.p - center) / radius;
		rec.pMaterial = pMaterial;
		return true;
	}
	return false;
}
